﻿using Cysharp.Threading.Tasks;
using HybridCLR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using YooAsset;
namespace Client.Base
{
    public class FsmStartGame : PatchState
    {
        public FsmStartGame(PatchProcess procedure) : base(procedure)
        {
        }

        public override async void OnEnter()
        {
            this.Log("[Patch] FsmStartGame.");
            await LoadMetadataForAOTAssemblies();
            await LoadHotUpdateAssemblies();
            await UniTask.Yield();
            await RunGameLogic();
        }

        private async UniTask LoadMetadataForAOTAssemblies()
        {
            HomologousImageMode mode = HomologousImageMode.SuperSet;
            var package = GetDllPackage();
            var handle = package.LoadAssetAsync("aots");
            await handle.ToUniTask();
            var data = handle.AssetObject as TextAsset;
            var dllNames = JsonConvert.DeserializeObject<List<string>>(data.text);
            foreach (var name in dllNames)
            {
                var dataHandle = package.LoadAssetAsync(name);
                await dataHandle.ToUniTask();
                if (dataHandle.Status != EOperationStatus.Succeed)
                {
                    Debug.Log($"[  il2cpp ] - AOT 加载失败 : {name}");
                    return;
                }
                var dllData = dataHandle.AssetObject as TextAsset;
                if (data == null)
                {
                    continue;
                }
                LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllData.bytes, mode);
                Debug.Log($"[  il2cpp ] - AOT 加载成功 : {name}");
            }
        }
        private async UniTask LoadHotUpdateAssemblies()
        {
            var package = GetDllPackage();
            var handle = package.LoadAssetAsync("hotfixs");
            await handle.ToUniTask();
            var data = handle.AssetObject as TextAsset;
            var dllNames = JsonConvert.DeserializeObject<List<string>>(data.text);
            foreach (var name in dllNames)
            {
                var dataHandle = package.LoadAssetAsync(name);
                await dataHandle.ToUniTask();
                if (dataHandle.Status != EOperationStatus.Succeed)
                {
                    Debug.LogError($"[  il2cpp ] - HOTFIX 加载失败 : {name}");
                    return;
                }
                var dllData = dataHandle.AssetObject as TextAsset;
                if (dllData == null)
                {
                    return;
                }
                Assembly assembly = Assembly.Load(dllData.bytes);
                Debug.Log($"[  il2cpp ] - HOTFIX 加载成功 : {name}");
            }
        }

        private async UniTask RunGameLogic()
        {
            try
            {
                Assembly ass = AppDomain.CurrentDomain.GetAssemblies().First(assembly => assembly.GetName().Name == "Hotfix.Runtime");
                Type entryType = ass.GetType("Client.Hotfix.Entry");
                GameObject go = new GameObject();
                go.AddComponent(entryType);
                await UniTask.Yield();
            }
            catch (Exception ex)
            {
                this.Error($"GameStart Fail! : {ex.Message}");
            }

        }

        private ResourcePackage GetDllPackage()
        {
            string pkName = string.Empty;
            for (int i = 0; i < YAPackageInfo.Setting.packages.Length; i++)
            {
                if (!YAPackageInfo.Setting.packages[i].isRaw)
                {
                    pkName = YAPackageInfo.Setting.packages[i].packageName;
                    break;
                }
            }
            return YooAssets.GetPackage(pkName);
        }

    }
}
